home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / editors / mjovesrc.zoo / extend.c < prev    next >
C/C++ Source or Header  |  1992-04-04  |  15KB  |  716 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is    *
  5.  * included in all the files.                                              *
  6.  ***************************************************************************/
  7.  
  8. #include "jove.h"
  9. #include "fp.h"
  10. #include "termcap.h"
  11. #include "ctype.h"
  12. #include "chars.h"
  13. #include "disp.h"
  14. #include "re.h"
  15.  
  16. #ifdef    IPROCS
  17. # include <signal.h>
  18. #endif
  19.  
  20. #ifdef    MAC
  21. # include "mac.h"
  22. #else
  23. # ifdef    STDARGS
  24. #  include <stdarg.h>
  25. # else
  26. #  include <varargs.h>
  27. # endif
  28. #endif
  29.  
  30. #ifdef    MSDOS
  31. # include <process.h>
  32. #endif
  33.  
  34. private void
  35.     DefAutoExec proto((struct data_obj *(*proc) ptrproto((const char *))));
  36.  
  37. private int
  38.     match proto((char **, char *));
  39.  
  40. int    InJoverc = 0;
  41.  
  42. /* Auto execute code */
  43.  
  44. #define NEXECS    20
  45.  
  46. private struct {
  47.     char    *a_pattern;
  48.     data_obj    *a_cmd;
  49. } AutoExecs[NEXECS];    /* must be initialized by system to 0 */
  50.  
  51. private int    ExecIndex = 0;
  52.  
  53. /* Command auto-execute. */
  54.  
  55. void
  56. CAutoExec()
  57. {
  58.     DefAutoExec(findcom);
  59. }
  60.  
  61. /* Macro auto-execute. */
  62.  
  63. void
  64. MAutoExec()
  65. {
  66.     DefAutoExec(findmac);
  67. }
  68.  
  69. private void
  70. DefAutoExec(proc)
  71. data_obj    *(*proc) ptrproto((const char *));
  72. {
  73.     data_obj    *d;
  74.     char    *pattern;
  75.     int    i;
  76.  
  77.     if (ExecIndex >= NEXECS)
  78.         complain("Too many auto-executes, max %d.", NEXECS);
  79.     if ((d = (*proc)(ProcFmt)) == NULL)
  80.         return;
  81.     pattern = do_ask("\r\n", (bool (*) ptrproto((int))) NULL, (char *) NULL, ": %f %s ",
  82.         d->Name);
  83.     for (i = 0; i < ExecIndex; i++) {
  84.         if (AutoExecs[i].a_cmd == d) {
  85.         char    *ipat = AutoExecs[i].a_pattern;
  86.  
  87.         if ((pattern == NULL || ipat == NULL)?
  88.             (pattern == ipat) : (strcmp(pattern, ipat) == 0))
  89.             return;        /* eliminate duplicates */
  90.         }
  91.     }
  92.     AutoExecs[ExecIndex].a_pattern = copystr(pattern);
  93.     AutoExecs[ExecIndex].a_cmd = d;
  94.     ExecIndex += 1;
  95. }
  96.  
  97. /* DoAutoExec: NEW and OLD are file names, and if NEW and OLD aren't the
  98.    same kind of file (i.e., match the same pattern) or OLD is NULL and it
  99.    matches, OR if the pattern is NULL (none was specified) then, we execute
  100.    the command associated with that kind of file. */
  101.  
  102. void
  103. DoAutoExec(new, old)
  104. register char    *new,
  105.         *old;
  106. {
  107.     register int    i;
  108.  
  109.     set_arg_value(1);
  110.     for (i = 0; i < ExecIndex; i++)
  111.         if ((AutoExecs[i].a_pattern == NULL) ||
  112.             ((new != NULL && LookingAt(AutoExecs[i].a_pattern, new, 0)) &&
  113.              (old == NULL || !LookingAt(AutoExecs[i].a_pattern, old, 0))))
  114.             ExecCmd(AutoExecs[i].a_cmd);
  115. }
  116.  
  117. int
  118. addgetc()
  119. {
  120.     int    c;
  121.  
  122.     if (!InJoverc) {
  123.         Asking = YES;
  124.         AskingWidth = strlen(mesgbuf);
  125.         c = getch();
  126.         Asking = NO;
  127.         add_mess("%p ", c);
  128.     } else {
  129.         c = getch();
  130.         if (c == '\n')
  131.             return EOF;    /* this isn't part of the sequence */
  132.         else if (c == '\\') {
  133.             if ((c = getch()) == LF)
  134.                 complain("[Premature end of line]");
  135.         } else if (c == '^') {
  136.             if ((c = getch()) == '?')
  137.                 c = RUBOUT;
  138.             else if (jisalpha(c) || strchr("@[\\]^_", c))
  139.                 c = CTL(c);
  140.             else
  141.                 complain("[Unknown control character]");
  142.         }
  143.     }
  144.     return c;
  145. }
  146.  
  147. void
  148. Extend()
  149. {
  150.     data_obj    *d;
  151.  
  152.     if ((d = findcom(": ")) != NULL)
  153.         ExecCmd(d);
  154. }
  155.  
  156. /* Read a positive integer from CP.  It must be in base BASE, and
  157.    complains if it isn't.  If allints is nonzero, all the characters
  158.    in the string must be integers or we return -1; otherwise we stop
  159.    reading at the first nondigit. */
  160.  
  161. int
  162. chr_to_int(cp, base, allints, result)
  163. register char    *cp;
  164. int    base,
  165.     allints;
  166. register int    *result;
  167. {
  168.     register int    c;
  169.     int    value = 0,
  170.         sign;
  171.  
  172.     if ((c = *cp) == '-') {
  173.         sign = -1;
  174.         cp += 1;
  175.     } else
  176.         sign = 1;
  177.     while ((c = *cp++) != '\0') {
  178.         if (!jisdigit(c)) {
  179.             if (allints == YES)
  180.                 return INT_BAD;
  181.             break;
  182.         }
  183.         c = c - '0';
  184.         if (c >= base)
  185.             complain("You must specify in base %d.", base);
  186.         value = value * base + c;
  187.     }
  188.     *result = value * sign;
  189.     return INT_OKAY;
  190. }
  191.  
  192. int
  193. ask_int(prompt, base)
  194. char    *prompt;
  195. int    base;
  196. {
  197.     char    *val = ask((char *)NULL, prompt);
  198.     int    value;
  199.  
  200.     if (chr_to_int(val, base, YES, &value) == INT_BAD)
  201.         complain("That's not a number!");
  202.     return value;
  203. }
  204.  
  205. void
  206. vpr_aux(vp, buf, size)
  207. register const struct variable    *vp;
  208. char    *buf;
  209. size_t    size;
  210. {
  211.     switch (vp->v_flags & V_TYPEMASK) {
  212.     case V_BASE10:
  213.         swritef(buf, size, "%d", *((int *) vp->v_value));
  214.         break;
  215.  
  216.     case V_BASE8:
  217.         swritef(buf, size, "%o", *((int *) vp->v_value));
  218.         break;
  219.  
  220.     case V_BOOL:
  221.         swritef(buf, size, (*((int *) vp->v_value)) ? "on" : "off");
  222.         break;
  223.  
  224.     case V_STRING:
  225.     case V_FILENAME:
  226.         swritef(buf, size, "%s", vp->v_value);
  227.         break;
  228.  
  229.     case V_CHAR:
  230.         swritef(buf, size, "%p", *((int *) vp->v_value));
  231.         break;
  232.     }
  233. }
  234.  
  235. void
  236. PrVar()
  237. {
  238.     struct variable    *vp;
  239.     char    prbuf[256];
  240.  
  241.     if ((vp = (struct variable *) findvar(ProcFmt)) == NULL)
  242.         return;
  243.     vpr_aux(vp, prbuf, sizeof(prbuf));
  244.     s_mess(": %f %s => %s", vp->Name, prbuf);
  245. }
  246.  
  247. void
  248. SetVar()
  249. {
  250.     struct variable    *vp;
  251.     char    prompt[128];
  252.  
  253.     if ((vp = (struct variable *) findvar(ProcFmt)) == NULL)
  254.         return;
  255.     swritef(prompt, sizeof(prompt), ": %f %s ", vp->Name);
  256.  
  257.     switch (vp->v_flags & V_TYPEMASK) {
  258.     case V_BASE10:
  259.     case V_BASE8:
  260.         *((int *) vp->v_value) = ask_int(prompt,
  261.             ((vp->v_flags & V_TYPEMASK) == V_BASE10)? 10 : 8);
  262.         break;
  263.  
  264.     case V_BOOL:
  265.         {
  266.         char    *def = *((bool *) vp->v_value) ? "off" : "on",
  267.             *on_off;
  268.         bool    value;
  269.  
  270.         on_off = ask(def, prompt);
  271.         if (casecmp(on_off, "on") == 0)
  272.             value = ON;
  273.         else if (casecmp(on_off, "off") == 0)
  274.             value = OFF;
  275.         else {
  276.             complain("Boolean variables must be ON or OFF.");
  277.             /* NOTREACHED */
  278.         }
  279.         *((bool *) vp->v_value) = value;
  280. #ifdef    MAC
  281.         MarkVar(vp,-1,0);    /* mark the menu item */
  282. #endif
  283.         s_mess("%s%s", prompt, value ? "on" : "off");
  284.         break;
  285.         }
  286.  
  287.     case V_FILENAME:
  288.         {
  289.         char    fbuf[FILESIZE];
  290.         size_t    pl = strlen(prompt);
  291.  
  292.         swritef(&prompt[pl], sizeof(prompt)-pl, "(default %s) ",
  293.             (char *)vp->v_value);
  294.         (void) ask_file(prompt, (char *) vp->v_value, fbuf);
  295.         strcpy((char *) vp->v_value, fbuf);
  296.         break;
  297.         }
  298.  
  299.     case V_STRING:
  300.         {
  301.         char    *str;
  302.  
  303.         /* Do_ask() so you can set string to "" if you so desire. */
  304.         str = do_ask("\r\n", (bool (*) ptrproto((int))) NULL,
  305.             (char *) vp->v_value, prompt);
  306.         if (str == NULL)
  307.             str = NullStr;
  308.         strcpy((char *) vp->v_value, str);
  309.         /* ... and hope there is enough room. */
  310.         break;
  311.         }
  312.     case V_CHAR:
  313.         f_mess(prompt);
  314.         *((int *) vp->v_value) = addgetc();
  315.         break;
  316.  
  317.     }
  318.     if (vp->v_flags & V_MODELINE)
  319.         UpdModLine = YES;
  320.     if (vp->v_flags & V_CLRSCREEN) {
  321. #ifdef    IBMPC
  322.         setcolor(Fgcolor, Bgcolor);
  323. #endif    /* IBMPC */
  324.         ClAndRedraw();
  325.     }
  326.     if (vp->v_flags & V_TTY_RESET)
  327.         tty_reset();
  328. }
  329.  
  330. /* Command completion - possible is an array of strings, prompt is
  331.    the prompt to use, and flags are ... well read jove.h.
  332.  
  333.    If flags are RET_STATE, and the user hits <return> what they typed
  334.    so far is in the Minibuf string. */
  335.  
  336. private char    **Possible;
  337. private int    comp_value,
  338.         comp_flags;
  339.  
  340. private bool
  341. aux_complete(c)
  342. int    c;
  343. {
  344.     int    command,
  345.         i;
  346.  
  347.     if (comp_flags & CASEIND) {
  348.         char    *lp;
  349.  
  350.         for (lp = linebuf; *lp != '\0'; lp++)
  351.             if (jisupper(*lp))
  352.                 *lp = jtolower(*lp);
  353.     }
  354.     switch (c) {
  355.     case EOF:
  356.         comp_value = -1;
  357.         return FALSE;
  358.  
  359.     case '\r':
  360.     case '\n':
  361.         command = match(Possible, linebuf);
  362.         if (command >= 0) {
  363.             comp_value = command;
  364.             return FALSE;    /* tells ask to stop */
  365.         }
  366.         if (eolp() && bolp()) {
  367.             comp_value = NULLSTRING;
  368.             return FALSE;
  369.         }
  370.         if (comp_flags & RET_STATE) {
  371.             comp_value = command;
  372.             return FALSE;
  373.         }
  374.         if (InJoverc)
  375.             complain("[\"%s\" unknown]", linebuf);
  376.         rbell();
  377.         break;
  378.  
  379.     case '\t':
  380.     case ' ':
  381.         {
  382.         int    minmatch = 1000,
  383.             maxmatch = 0,
  384.             numfound = 0,
  385.             lastmatch = -1,
  386.             len = strlen(linebuf);
  387.  
  388.         for (i = 0; Possible[i] != 0; i++) {
  389.             int    this_len;
  390.  
  391.             this_len = numcomp(Possible[i], linebuf);
  392.             maxmatch = max(maxmatch, this_len);
  393.             if (this_len >= len) {
  394.                 if (numfound)
  395.                     minmatch = min(minmatch, numcomp(Possible[lastmatch], Possible[i]));
  396.                 else
  397.                     minmatch = strlen(Possible[i]);
  398.                 numfound += 1;
  399.                 lastmatch = i;
  400.                 if (strcmp(linebuf, Possible[i]) == 0)
  401.                     break;
  402.             }
  403.         }
  404.  
  405.         if (numfound == 0) {
  406.             rbell();
  407.             if (InJoverc)
  408.                 compl